package com.limespot.api.tree;

import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;

import javax.swing.JTree;
import javax.swing.SwingUtilities;
import javax.swing.event.TreeExpansionEvent;
import javax.swing.event.TreeExpansionListener;
import javax.swing.tree.DefaultTreeModel;

import com.limespot.api.User;

public class LimeSpotTreeModel extends DefaultTreeModel { //implements TreeModel {
	
	private static final long	serialVersionUID	= -322575517380005198L;
	private final Callback callback;
	
	public interface Callback {
		void update(String msg);
		Callback DEFAULT = new Callback() {
			public void update(String msg) {}			
		};
	}
	
	public LimeSpotTreeModel(final JTree tree, User user, Callback callback) {
		super(new UserTreeNode(user));
		this.callback = callback == null ? Callback.DEFAULT : callback;
		tree.addTreeExpansionListener(new TreeExpansionListener() {
			
			private final Set<Integer> seen = new HashSet<Integer>();

			public void treeCollapsed(TreeExpansionEvent event) {
				// nothing
			}

			public void treeExpanded(final TreeExpansionEvent event) {
				final UserTreeNode node = (UserTreeNode)event.getPath().getLastPathComponent();
				Integer hash = System.identityHashCode(node);
				if (seen.contains(hash)) return;
				seen.add(hash);
				SwingUtilities.invokeLater(new Runnable() {
					public void run() {
						User user = (User)node.getUserObject();
						for (Iterator<User> it = user.getContacts().iterator(); it.hasNext();) {
							User u = it.next();
							update("adding " + u);
							UserTreeNode newNode = new UserTreeNode(u);
							node.add(newNode);
						}
						tree.updateUI();
						tree.expandPath(event.getPath());
					}
				});
			}
			
		});
	}
	
	public LimeSpotTreeModel(JTree tree, User user) {
		this(tree, user,null);
	}
	
	// -------------------------------------------------------------------
	// Interface
	// -------------------------------------------------------------------

//	public void addTreeModelListener(TreeModelListener l) {
//		if (!treeModelListeners.contains(l)) {
//			treeModelListeners.add(l);
//		}
//	}

//	public Object getChild(Object parent, int index) {
//		UserTreeNode n = (UserTreeNode)parent;
//		return n.getChildAt(index);
//	}
//
//	public int getChildCount(Object parent) {
//		UserTreeNode n = (UserTreeNode)parent;
//		return n.getChildCount();
//	}
//
//	public int getIndexOfChild(Object parent, Object child) {
//		UserTreeNode n = (UserTreeNode)parent;
//		return n.getIndex((UserTreeNode)child);
//	}
//
//	public Object getRoot() {
//		return root;
//	}
//
//	public boolean isLeaf(Object node) {
//		return false;
//	}
//
//	public void removeTreeModelListener(TreeModelListener l) {
//		if (treeModelListeners.contains(l)) {
//			treeModelListeners.remove(l);
//		}
//	}
//
//	public void valueForPathChanged(TreePath path, Object newValue) {
//		final TreeModelEvent e = new TreeModelEvent(newValue,path);
//		for (TreeModelListener l : treeModelListeners) {
//			l.treeNodesChanged(e);
//		}
//	}
	
	// -------------------------------------------------------------------
	// Misc
	// -------------------------------------------------------------------

	private void update(String msg) {
		callback.update(msg);
	}
}
